home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Programming / tek / task / createtask.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-05-12  |  6.4 KB  |  270 lines

  1.  
  2. #include "tek/exec.h"
  3. #include "tek/debug.h"
  4. #include "tek/kn/exec.h"
  5.  
  6. /* 
  7. **    TEKlib
  8. **    (C) 2001 TEK neoscientists
  9. **    all rights reserved.
  10. **
  11. **    TAPTR TCreateTask(TAPTR parenttask, TTASKFUNC function, TTAGITEM *tags)
  12. **
  13. **    create task.
  14. **
  15. **    tags:
  16. **        TTask_MMU                mmu to allocate task structures from, default: the basetask's heap mmu
  17. **        TTask_HeapMMU            mmu to put task's heap mmu on, default: TTask_MMU
  18. **        TTask_InitFunc            init function, default: TNULL
  19. **
  20. **    TODO: fixme: user-specified TTask_HeapMMU is currently overwritten with a pool allocator!!! (stimmt garnicht, oder?)
  21. **    TODO: return a task return value with TDestroy(task) ?
  22. **    TODO: add user TTask_MsgMMU tag
  23. **
  24. */
  25.  
  26. static TINT destroytask(TTASK *task);
  27. static TVOID taskentryfunc(TTASK *task);
  28.  
  29. TAPTR TCreateTask(TAPTR parenttask, TTASKFUNC function, TTAGITEM *taglist)
  30. {
  31.     TTASKINITFUNC initfunction = (TTASKINITFUNC) TGetTagValue(TTask_InitFunc, TNULL, taglist);
  32.     
  33.     if (!(function || initfunction) == !parenttask)
  34.     {
  35.         TAPTR parentmmu = TGetTagValue(TTask_MMU, parenttask ? 
  36.             &((TTASK *)((TTASK *) parenttask)->basetask)->heapmmu : TNULL, taglist);
  37.  
  38.         TTASK *newtask = TMMUAllocHandle0(parentmmu, (TDESTROYFUNC) destroytask, sizeof(TTASK));
  39.         if (newtask)
  40.         {
  41.             newtask->heapallocator = TGetTagValue(TTask_HeapMMU, parentmmu, taglist);
  42.  
  43.             if (parenttask)
  44.             {
  45.                 /*
  46.                 **    create new context.
  47.                 */
  48.                 
  49.                 if (kn_initlock(&newtask->siglock))
  50.                 {
  51.                     if (kn_initlock(&newtask->runlock))
  52.                     {
  53.                         if (kn_initevent(&newtask->statusevent))
  54.                         {
  55.                             newtask->basetask = ((TTASK *) parenttask)->basetask;
  56.                             newtask->msgmmu = ((TTASK *) (newtask->basetask))->msgmmu;
  57.                             newtask->func = function;
  58.                             newtask->initfunc = initfunction;
  59.                             newtask->userdata = TGetTagValue(TTask_UserData, TNULL, taglist);
  60.                             newtask->sigstate = 0;
  61.                             newtask->sigfree = ~TTASK_SIG_RESERVED;
  62.                             newtask->sigused = TTASK_SIG_RESERVED;
  63.                             newtask->status = TTASK_STATUS_INITIALIZING;
  64.                 
  65.                             kn_lock(&newtask->runlock);
  66.             
  67.                             if (kn_initthread(&newtask->thread, (TVOID (*)(TAPTR data)) taskentryfunc, newtask))
  68.                             {
  69.                                 kn_unlock(&newtask->runlock);
  70.  
  71.                                 kn_waitevent(&newtask->statusevent);
  72.  
  73.  
  74.                                 #ifndef TEKLIB_PTHREADS_FLAW
  75.  
  76.                                     kn_destroyevent(&newtask->statusevent);    
  77.                                 
  78.                                     /* race condition in pthreads? */
  79.  
  80.                                 #endif
  81.  
  82.  
  83.                                 if (newtask->status != TTASK_STATUS_FAILED)
  84.                                 {
  85.                                     return newtask;
  86.                                 }
  87.                             }
  88.                             else
  89.                             {
  90.                                 kn_unlock(&newtask->runlock);
  91.                             }
  92.                         }
  93.                         kn_destroylock(&newtask->runlock);
  94.                     }
  95.                     kn_destroylock(&newtask->siglock);
  96.                 }
  97.             }
  98.             else
  99.             {
  100.                 /*
  101.                 **    establish base context.
  102.                 */
  103.             
  104.                 newtask->heapallocator = TCreatePool(newtask->heapallocator, 1024, 512, TNULL);
  105.                 if (newtask->heapallocator)
  106.                 {
  107.                     if (TInitMMU(&newtask->heapmmu, newtask->heapallocator, TMMUT_Pooled+TMMUT_TaskSafe, TNULL))
  108.                     {
  109.                         newtask->msgmmu = TMMUAlloc(&newtask->heapmmu, sizeof(TMMU));
  110.                         if (newtask->msgmmu)
  111.                         {
  112.                             if (TInitMMU(newtask->msgmmu, TNULL, TMMUT_Message, TNULL))
  113.                             {
  114.                                 if (kn_inittimer(&newtask->timer))
  115.                                 {
  116.                                     if (kn_initlock(&newtask->siglock))
  117.                                     {
  118.                                         if (kn_initevent(&newtask->sigevent))
  119.                                         {
  120.                                             newtask->basetask = newtask;
  121.                                             newtask->sigstate = 0;
  122.                                             newtask->sigfree = ~TTASK_SIG_RESERVED;
  123.                                             newtask->sigused = TTASK_SIG_RESERVED;
  124.                                             
  125.                                             if (kn_initbasecontext(&newtask->thread, newtask))
  126.                                             {
  127.                                                 newtask->port = TCreatePort(newtask, TNULL);
  128.                                                 if (newtask->port)
  129.                                                 {
  130.                                                     newtask->syncreplyport = TCreatePort(newtask, TNULL);
  131.                                                     if (newtask->syncreplyport)
  132.                                                     {
  133.                                                         newtask->status = TTASK_STATUS_RUNNING;
  134.                                                         return newtask;
  135.                                                     }
  136.                                                     TDestroy(newtask->port);
  137.                                                 }
  138.                                                 kn_destroybasecontext(&newtask->thread);
  139.                                             }
  140.                                             kn_destroyevent(&newtask->sigevent);
  141.                                         }
  142.                                         kn_destroylock(&newtask->siglock);
  143.                                     }
  144.                                     kn_destroytimer(&newtask->timer);
  145.                                 }
  146.                                 TDestroy(newtask->msgmmu);
  147.                             }
  148.                             TMMUFree(&newtask->heapmmu, newtask->msgmmu);        /* redundant */
  149.                         }
  150.                         TDestroy(&newtask->heapmmu);
  151.                     }
  152.                     TDestroy(newtask->heapallocator);
  153.                 }
  154.             }
  155.             TMMUFreeHandle(newtask);
  156.         }
  157.     }
  158.  
  159.     tdbprintf(10, "*** TEKLIB: createtask failed\n");
  160.     
  161.     return TNULL;
  162. }
  163.  
  164.  
  165. static TVOID taskentryfunc(TTASK *task)
  166. {
  167.     TBOOL success = TFALSE;
  168.  
  169.     if (kn_inittimer(&task->timer))
  170.     {
  171.         if (kn_initevent(&task->sigevent))
  172.         {
  173.             task->heapallocator = TCreatePool(task->heapallocator, 512, 256, TNULL);
  174.             if (task->heapallocator)
  175.             {
  176.                 if (TInitMMU(&task->heapmmu, task->heapallocator, TMMUT_TaskSafe+TMMUT_Pooled, TNULL))
  177.                 {
  178.                     task->port = TCreatePort(task, TNULL);
  179.                     if (task->port)
  180.                     {
  181.                         task->syncreplyport = TCreatePort(task, TNULL);
  182.                         if (task->syncreplyport)
  183.                         {
  184.                             success = TTRUE;
  185.  
  186.                             if (task->initfunc)
  187.                             {
  188.                                 success = (*task->initfunc)(task);
  189.                             }
  190.  
  191.                             if (success)
  192.                             {
  193.                                 kn_lock(&task->runlock);
  194.             
  195.                                 task->status = TTASK_STATUS_RUNNING;
  196.                                 kn_doevent(&task->statusevent);
  197.             
  198.                                 if (task->func)
  199.                                 {
  200.                                     (*task->func)(task);
  201.                                 }
  202.                             }
  203.                 
  204.                             TDestroy(task->syncreplyport);
  205.                         }
  206.                         TDestroy(task->port);
  207.                     }
  208.                     TDestroy(&task->heapmmu);
  209.                 }
  210.                 TDestroy(task->heapallocator);
  211.             }
  212.             kn_destroyevent(&task->sigevent);
  213.         }
  214.         kn_destroytimer(&task->timer);
  215.     }
  216.  
  217.     kn_deinitthread(&task->thread);
  218.  
  219.     if (success)
  220.     {
  221.         task->status = TTASK_STATUS_FINISHED;
  222.         kn_unlock(&task->runlock);
  223.     }
  224.     else
  225.     {
  226.         task->status = TTASK_STATUS_FAILED;
  227.         kn_doevent(&task->statusevent);
  228.     }
  229. }
  230.  
  231.  
  232.  
  233. static TINT destroytask(TTASK *task)
  234. {
  235.     if (task->basetask != task)
  236.     {
  237.         kn_lock(&task->runlock);
  238.  
  239.         #ifdef TEKLIB_PTHREADS_FLAW
  240.  
  241.             kn_destroyevent(&task->statusevent);
  242.             
  243.             /* race condition in pthreads? */
  244.  
  245.         #endif
  246.  
  247.         kn_unlock(&task->runlock);
  248.         kn_destroylock(&task->runlock);
  249.         kn_destroylock(&task->siglock);
  250.         kn_destroythread(&task->thread);
  251.     }
  252.     else
  253.     {
  254.         TDestroy(task->syncreplyport);
  255.         TDestroy(task->port);
  256.         kn_destroybasecontext(&task->thread);
  257.         kn_destroyevent(&task->sigevent);
  258.         kn_destroylock(&task->siglock);
  259.         kn_destroytimer(&task->timer);
  260.         TDestroy(task->msgmmu);
  261.         TMMUFree(&task->heapmmu, task->msgmmu);
  262.         TDestroy(&task->heapmmu);
  263.         TDestroy(task->heapallocator);
  264.     }
  265.  
  266.     TMMUFreeHandle(task);
  267.  
  268.     return 0;
  269. }
  270.